package com.zy.explore.client.infrastructure.aspect;


import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;

/**
 * description 日志切面
 * 注意，execution中的包路径！
 *
 * @author 🇨🇳中国印🇨🇳
 * @date 2022年04月17日 02:38:46
 */
@Component
@Aspect
@Slf4j
public class ProjectLogAspect {

    @Value("${spring.profiles.active:}")
    private String env;

    /**
     * 控制器层controller中所有方法的日志
     */
    @Pointcut("execution(* com.zy.explore.client.interfaces.facade.*..*(..))")
    public void webLog() {
    }

    /**
     * 后置通知
     *
     * @param ret 方法返回对象
     */
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) {

    }

    /**
     * 统计切面方法执行时间
     *
     * @author 🇨🇳中国印🇨🇳
     * @date 2022年04月17日 02:38:46
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        // result 为方法的返回值
        Object result = pjp.proceed();
        long end = System.currentTimeMillis();
        // 获取请求、响应对象
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attrs != null;
        HttpServletRequest request = attrs.getRequest();
        HttpServletResponse response = attrs.getResponse();
        // 响应
        String retObjStr = "";
        if (result != null) {
            retObjStr = JSON.toJSONString(result);
        }

        int strLength = 100;
        // 本地和开发环境则切面日志打印多些
        List<String> envList = Arrays.asList("local", "dev");
        if (envList.contains(env)) {
            strLength = 10000;
        }
        if (!StringUtils.isEmpty(retObjStr) && retObjStr.length() > strLength) {
            retObjStr = retObjStr.substring(0, strLength);
        }
        assert response != null;
        log.info("请求IP:{}, 状态码:{}, 请求URI:{} 请求参数：{} 耗时:{}ms 返回值：{}", request.getRemoteAddr(), response.getStatus(), request.getRequestURL(), Arrays.toString(pjp.getArgs()), (end - start), retObjStr);
        return result;
    }
}